#!/bin/bash
# 
# Implemented by maminjie1@huawei.com
#

token_file=~/.gitee_token.json
if [ ! -f $token_file ]; then
    echo "Please execute prepare_token.sh to generate token!"; exit
fi
access_token=$(grep "access_token" $token_file | awk -F '[,:]' '{print $2}' | sed 's/"//g')
if [ -z $access_token ]; then
    echo "access_token is empty!"; exit
fi
gitee_owner=src-openeuler
gitee_id=""
gitee_pwd=""

readonly OEC_VERSION="0.1.0"

readonly COLOR_NONE="\033[0m"
readonly COLOR_RED="\033[0;31m"
readonly COLOR_GREEN="\033[0;32m"

###############################################################################
# gitee.sh
#
# Refers to https://gitee.com/api/v5/swagger
#
readonly GITEE_HEADER="Content-Type: application/json;charset=UTF-8"
readonly GITEE_URL_PREFIX="https://gitee.com/api/v5/repos"

# fork_repo(repo)
#   Fork the specified repo
# Example:
#   fork_repo fancytool
fork_repo() {
    curl -X POST --header "$GITEE_HEADER" "$GITEE_URL_PREFIX/$gitee_owner/$1/forks" \
        -d "{\"access_token\":\"$access_token\"}" &>/dev/null
}

# create_pr(repo, title)
#   Create Pull Request
# Example:
#   create_pr fancytool "update scripts"
create_pr() {
    curl -X POST --header "$GITEE_HEADER" "$GITEE_URL_PREFIX/$gitee_owner/$1/pulls" \
        -d "{\"access_token\":\"$access_token\",\"title\":\"$2\",\"head\":\"$gitee_id:master\",\"base\":\"master\"}" &>/dev/null
}

# get_pr_comments(repo, number)
#   Get all comments of a Pull Request
# Returns:
#   the http response body string
# Example:
#   result=$(get_pr_comments fancytool 1)
get_pr_comments() {
    local result=$(curl -s -X GET --header "$GITEE_HEADER" "$GITEE_URL_PREFIX/$gitee_owner/$1/pulls/$2/comments" \
        -d "{\"access_token\":\"$access_token\",\"page\":\"1\",\"per_page\":\"20\"}")
    echo "$result"
}

# comment_pr(repo, number, comments)
#   Submit Pull Request comments
# Example
#   comment_pr fancytool 1 "OK"
comment_pr() {
    curl -X POST --header "$GITEE_HEADER" "$GITEE_URL_PREFIX/$gitee_owner/$1/pulls/$2/comments" \
        -d "{\"access_token\":\"$access_token\",\"body\":\"$3\"}" &>/dev/null
}

# check_pr_merge(repo, number)
#   Determine whether the Pull Request has been merged
# Returns:
#       1 - megerd
#       0 - opened
# Example:
#   result=$(check_pr_merge fancytool 1)
check_pr_merge() {
    local result=$(curl -s -X GET -w '%{http_code}' --header $GITEE_HEADER "$GITEE_URL_PREFIX/$gitee_owner/$1/pulls/$2/merge" \
        -d "{\"access_token\":\"$access_token\"}" | grep -o "200")
    if [ "$result" = "200" ]; then
        return 1
    else
        return 0
    fi
}
###############################################################################

get_list() {
    local lst=""

    if [ -f "$1" ]; then
        lst=$(cat $1)
    else
        lst=$1
    fi

    echo $lst
}

check_pr_compile() {
    result=$(get_pr_comments $1 $2 | sed -e 's/\s//g' -e 's/\n//g' -e 's/body/\n/g')
    for i in $result; do
        cnt=$(echo $i | grep -o "SUCCESS" | wc -w)
        if [ $(echo $i | grep -o "check_code_style" | wc -w) -eq 1 ]; then
            expected_cnt=4
        else 
            expected_cnt=3
        fi
        if [ $cnt -eq $expected_cnt ]; then
            return 1
        fi
    done
    return 0
}

# fun pr_list
do_check_pr_merge() {  
    local pr_open_file=pr_open.txt
    local pr_merge_file=pr_merge.txt
    local pr_list=$(get_list "$1")

    rm -f $pr_merge_file $pr_open_file
    for pr in $pr_list; do
        printf "checking merge $pr"
        repo_pn=$(echo $pr | sed -e "s|.*$gitee_owner/||g" -e 's|/pulls/| |g')
        check_pr_merge $repo_pn
        if [ $? == 1 ]; then
            printf " (${COLOR_GREEN}merged${COLOR_NONE})\n"
            echo "$pr" >> $pr_merge_file
        else
            printf " (${COLOR_RED}opened${COLOR_NONE})\n"
            echo "$pr" >> $pr_open_file
        fi
    done
    echo "========================================="
    echo "Please check $pr_open_file and $pr_merge_file"
    echo "========================================="
}

# fun pr_list
do_check_pr_compile() {
    local pr_fail_file=pr_fail.txt
    local pr_succ_file=pr_succ.txt
    local pr_list=$(get_list "$1")

    rm -f $pr_fail_file $pr_succ_file
    for pr in $pr_list; do
        printf "checking compile $pr"
        repo_pn=$(echo $pr | sed -e "s|.*$gitee_owner/||g" -e 's|/pulls/| |g')
        check_pr_compile $repo_pn
        if [ $? == 1 ]; then
            printf " (${COLOR_GREEN}success${COLOR_NONE})\n"
            echo "$pr" >> $pr_succ_file
        else
            printf " (${COLOR_RED}fail${COLOR_NONE})\n"
            echo "$pr" >> $pr_fail_file
        fi
    done
    echo "========================================"
    echo "Please check $pr_fail_file and $pr_succ_file"
    echo "========================================"
}

# fun pr_list comments
do_submit_comment() {
    local pr_list=$(get_list "$1")

    for pr in $pr_list; do
        echo "comment $pr \"$2\""
        repo_pn=$(echo $pr | sed -e "s|.*$gitee_owner/||g" -e 's|/pulls/| |g')
        comment_pr $repo_pn "$2"
    done
}

read_account() {
    read -p "Username for GITEE: " gitee_id
    if [ -z $gitee_id ]; then
        echo "gitee id invalid"
        exit 1
    fi
    stty -echo
    read -p "Password for GITEE: " gitee_pwd
    stty echo
    if [ -z $gitee_pwd ]; then
        echo "gitee password invalid"
        exit 2
    fi
}

# func src_dir dst_dir repo
push_code() {
    local src_dir=$1
    local dst_dir=$2
    local repo=$3
    local srcpath=$src_dir/$repo
    local dstpath=$dst_dir/$repo

    # clone
    if [ ! -d $dstpath ]; then
        pushd $dst_dir
        git clone https://gitee.com/$gitee_id/$repo.git
        popd
    fi

    if [ ! -d $srcpath ] || [ ! -d $dstpath ]; then
        exit
    fi

    cp $srcpath/* $dstpath
    pushd $dstpath
    git add .
    git commit -m "package init"
    expect -c "
    spawn git push origin master
    expect {
    \"*Username*\" {send \"${gitee_id}\r\";exp_continue}
    \"*Password*\" {send \"${gitee_pwd}\r\";exp_continue}
    }
    "
    popd
}

# func src_dir dst_dir repo_list
do_push_code() {
    local src_dir=$1
    local dst_dir=$2
    local repo_list=$(get_list "$3")

    if [ -n $repo_list ]; then
        read_account
    fi

    for pkg in $repo_list; do
        fork_repo $pkg
        sleep 2
        push_code $src_dir $dst_dir $pkg
        create_pr $pkg "package init"
        sleep 1
    done
}

usage() {
    echo "Usage: oec [GLOBALOPTS] SUBCOMMAND [OPTS] [ARGS...]"
    echo "or: oec help SUBCOMMAND"
    echo ""
    echo "openEuler command-line tools."
    echo "Type 'oec help <subcommand>' for help on a specific subcommand."
    echo ""
    echo "Commands:"
    echo "      pushcode (pc)"
    echo "                          Auto push code. Steps contain fork, clone, push, pr."
    echo "      checkcompile (cc, ccpr)"
    echo "                          Check the Pull Request compile result"
    echo "      checkmerge (cm, cmpr)"
    echo "                          Check the Pull Request merge result"
    echo "      submitcomment (sc, scpr)"
    echo "                          Submit the Pull Request comments"
    echo "      help (?, h)         Give detailed help on a specific sub-command"
    echo ""
    echo "Global Options:"
    echo "      -v, --version       Show program's version number and exit"
    echo "      -h, --help          Show this help message and exit"
    echo ""
}

usage_pushcode() {
    echo "pushcode (pc): Auto push code. Steps contain fork, clone, push, pr."
    echo ""
    echo "Usage:"
    echo "      oec pc SOURCEDIR TARGETDIR PKGLIST"
    echo "      oec pc SOURCEDIR TARGETDIR LISTFILE"
    echo ""
    echo "Args:"
    echo "      SOURCEDIR           The source directory that contains specific packages"
    echo "      TARGETDIR           The target directory, where the packages are generally cloned from gitrepo"
    echo "      PKGLIST             The package name list, like: \"a b c d\""
    echo "      LISTFILE            The file that contains package name list"
    echo "                          Where each name is separated by a space or newline"
    echo ""
    echo "Examples:"
    echo "      oec pc /home/mine/src /home/mine/dst \"a b\""
    echo "                          Submit the two packages a and b to gitee."
    echo "                          sourcefiles in /home/mine/src and repos are cloned in /home/mine/dst"
    echo ""
}

usage_checkcompile() {
    echo "checkcompile (cc, ccpr): Check the Pull Request compile result"
    echo ""
    echo "Usage:"
    echo "      oec cc PRLIST"
    echo "      oec cc LISTFILE"
    echo ""
    echo "Args:"
    echo "      PRLIST              The PR list"
    echo "                          like: \"https://gitee.com/owner/repo1/pulls/1 https://gitee.com/owner/repo2/pulls/2\""
    echo "      LISTFILE            The file that contains PR list"
    echo "                          Where each PR is separated by a space or newline"
    echo ""
    echo "Examples:"
    echo "      oec cc \"https://gitee.com/$gitee_owner/repo1/pulls/1\""
    echo ""
}

usage_checkmerge() {
    echo "checkmerge (cm, cmpr): Check the Pull Request merge result"
    echo ""
    echo "Usage:"
    echo "      oec cm PRLIST"
    echo "      oec cm LISTFILE"
    echo ""
    echo "Args:"
    echo "      PRLIST              The PR list"
    echo "                          like: \"https://gitee.com/owner/repo1/pulls/1 https://gitee.com/owner/repo2/pulls/2\""
    echo "      LISTFILE            The file that contains PR list"
    echo "                          Where each PR is separated by a space or newline"
    echo ""
    echo "Examples:"
    echo "      oec cm \"https://gitee.com/$gitee_owner/repo1/pulls/1\""
    echo ""
}

usage_submitcomment() {
    echo "submitcomment (sc, scpr): Submit the Pull Request comments"
    echo ""
    echo "Usage:"
    echo "      oec sc PRLIST COMMENTS"
    echo "      oec sc LISTFILE COMMENTS"
    echo ""
    echo "Args:"
    echo "      PRLIST              The PR list"
    echo "                          like: \"https://gitee.com/owner/repo1/pulls/1 https://gitee.com/owner/repo2/pulls/2\""
    echo "      LISTFILE            The file that contains PR list"
    echo "                          Where each PR is separated by a space or newline"
    echo ""
    echo "Examples:"
    echo "      oec sc \"https://gitee.com/$gitee_owner/repo1/pulls/1\" \"/retest\""
    echo ""
}

do_help() {
    case $1 in
        "pushcode"|"pc")
            usage_pushcode
            ;;
        "checkcompile"|"cc"|"ccpr")
            usage_checkcompile
            ;;
        "checkmerge"|"cm"|"cmpr")
            usage_checkmerge
            ;;
        "submitcomment"|"sc"|"scpr")
            usage_submitcomment
            ;;
        *)
            usage
            ;;
    esac
}

main() {
    local subcmd=$1

    if [ $# -gt 0 ]; then
        shift
    fi

    case $subcmd in
        "pushcode"|"pc")
            do_push_code "$@"
            ;;
        "checkcompile"|"cc"|"ccpr")
            do_check_pr_compile "$@"
            ;;
        "checkmerge"|"cm"|"cmpr")
            do_check_pr_merge "$@"
            ;;
        "submitcomment"|"sc"|"scpr")
            do_submit_comment "$@"
            ;;
        "help"|"?"|"h")
            do_help "$@"
            ;;
        "-v"|"--version")
            echo "$OEC_VERSION"
            ;;
        *)
            usage
            ;;
    esac
}

main "$@"

